package root.root;

import java.io.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileDescriptor;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.Socket;
import java.net.URL;
import java.util.Enumeration;
import java.util.List;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;

import android.app.Activity;
import android.app.AlertDialog;
import android.app.Dialog;
import android.app.ProgressDialog;
import android.os.Bundle;
import android.os.Handler;
import android.util.Log;
import android.view.KeyEvent;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.TextView;

public class root extends Activity {
	/** Called when the activity is first created. */
	List<String> files;
	Dialog dlMessage;
	private Handler handler = new Handler();
	private root context;
	String dataPath;

	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.main);

		context = this;
		//dataPath = this.getFilesDir().getParent() + "/";
		dataPath = "/sdcard/";

		Button Button1 = (Button)findViewById(R.id.ButtonNBH);
		Button1.setOnClickListener(ButtonListener);
		Button Button2 = (Button)findViewById(R.id.ButtonJF);
		Button2.setOnClickListener(ButtonListener);
		Button Button3 = (Button)findViewById(R.id.ButtonIMGSPL);
		Button3.setOnClickListener(ButtonListener);
		Button Button4 = (Button)findViewById(R.id.ButtonROOT);
		Button4.setOnClickListener(ButtonListener);

	}
	private void CheckDLFile(String filename, boolean forceUnpack)
	{
		final String localPath = dataPath + filename;
		File file = new File(localPath);
		if (!file.exists() || forceUnpack)
		{
			final String sfilename = filename;
			Thread thread = new Thread(new Runnable() {
				public void run() {
					unpack(sfilename, localPath);
					exec("/system/bin/chmod", "755", localPath);
				}
			});
			thread.start();
		}
	}
	private void RenameFile (String file, String newFile)
	{
		File afile = new File(file);
		File anewFile = new File(newFile);
		afile.renameTo(anewFile);
	}
	private static final void copyInputStream(InputStream in, OutputStream out)
	throws IOException
	{// does not seem to work past 25MB
		byte[] buffer = new byte[1024];
		int len;

		while((len = in.read(buffer)) >= 0)
			out.write(buffer, 0, len);

		in.close();
		out.close();
	}

	private String unzipFile(String file)
	{// unzips only one file, should not have more than one file in zip
		Enumeration<?> entries;
		ZipFile zipFile;

		try {
			zipFile = new ZipFile(file);

			entries = zipFile.entries();

			while(entries.hasMoreElements()) {
				ZipEntry entry = (ZipEntry)entries.nextElement();

				FileOutputStream FOS = new FileOutputStream("/sdcard/" + entry.getName());

				copyInputStream(zipFile.getInputStream(entry), new BufferedOutputStream(FOS));
				return entry.getName();
			}

			zipFile.close();
		} catch (IOException ioe) {
			ioe.printStackTrace();
			return "";
		}
		return "";    	
	}
	private String exec(String arg0, String arg1, String arg2) {
		try {
			// android.os.Exec is not included in android.jar so we need to use reflection.
			Class<?> execClass = Class.forName("android.os.Exec");
			Method createSubprocess = execClass.getMethod("createSubprocess",
					String.class, String.class, String.class, int[].class);
			Method waitFor = execClass.getMethod("waitFor", int.class);
			createSubprocess.setAccessible(true);
			waitFor.setAccessible(true);
			// Executes the command.
			// NOTE: createSubprocess() is asynchronous.
			int[] pid = new int[1];
			FileDescriptor fd = (FileDescriptor)createSubprocess.invoke(
					null, arg0, arg1, arg2, pid);

			// Reads stdout.
			// NOTE: You can write to stdin of the command using new FileOutputStream(fd).
			FileInputStream in = new FileInputStream(fd);
			//FileOutputStream out = new FileOutputStream(fd);
			BufferedReader reader = new BufferedReader(new InputStreamReader(in));
			//BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(out));

			String output = "";
			try {
				int a=reader.read();
				while (a != -1){
					output += (char) a;
					if(output.endsWith("exit"))
						break;
					else
						a=reader.read();
				}
				reader.close();
				in.close();
				//writer.close();
				reader = null;
				in = null;
				//writer = null;
			} catch (IOException e) {
				// It seems IOException is thrown when it reaches EOF.
			}	

			// Waits for the command to finish.
			waitFor.invoke(null, pid[0]);
			return output;

		} catch (ClassNotFoundException e) {
			throw new RuntimeException(e.getMessage());
		} catch (SecurityException e) {
			throw new RuntimeException(e.getMessage());
		} catch (NoSuchMethodException e) {
			throw new RuntimeException(e.getMessage());
		} catch (IllegalArgumentException e) {
			throw new RuntimeException(e.getMessage());
		} catch (IllegalAccessException e) {
			throw new RuntimeException(e.getMessage());
		} catch (InvocationTargetException e) {
			throw new RuntimeException(e.getMessage());
		}
	}
	private void unpack(String filename, String localPath) {
		try {
			InputStream in = this.getAssets().open(filename);
			FileOutputStream out = new FileOutputStream(localPath);
			int read;
			byte[] buffer = new byte[4096];
			while ((read = in.read(buffer)) > 0) {
				out.write(buffer, 0, read);
			}
			out.close();
			in.close();
		} catch (MalformedURLException e) {
			throw new RuntimeException(e.getMessage());
		} catch (IOException e) {
			throw new RuntimeException(e.getMessage());
		}
	}


	private String download(String urlStr, String localPath) {
		try {
			URL url = new URL(urlStr);
			String[] split = urlStr.split("/");
			String filename = split[split.length-1];
			localPath = localPath + filename;
			HttpURLConnection urlconn = (HttpURLConnection)url.openConnection();
			urlconn.setRequestMethod("GET");
			urlconn.setInstanceFollowRedirects(true);
			urlconn.connect();
			InputStream in = urlconn.getInputStream();
			FileOutputStream out = new FileOutputStream(localPath);
			int read;
			byte[] buffer = new byte[4096];
			while ((read = in.read(buffer)) > 0) {
				out.write(buffer, 0, read);
			}
			out.close();
			in.close();
			urlconn.disconnect();
			return localPath;
		} catch (MalformedURLException e) {
			throw new RuntimeException(e.getMessage());
		} catch (IOException e) {
			throw new RuntimeException(e.getMessage());
		}
	}
	private void displayMsg(final String str) {
		Runnable proc = new Runnable() {
			public void run() {
				Dialog about = new AlertDialog.Builder(context)
				.setPositiveButton("ok", null)
				.setMessage(str)
				.create();
				about.show();
			}
		};
		handler.post(proc);
	}
	private OnClickListener ButtonListener = new OnClickListener()
	{
		public void onClick(View v)
		{
			TextView tv;
			Thread thread;
			final int butID = v.getId();
			final String msg;
			switch (butID)
			{
			case R.id.ButtonNBH:
				msg = (String)context.getText(R.string.preNBHmsg);
				break;
			case R.id.ButtonIMGSPL:
				msg = (String)context.getText(R.string.preIMGSPLmsg);
				break;
			case R.id.ButtonROOT:
				msg = (String)context.getText(R.string.preROOTmsg);
				break;
			case R.id.ButtonJF:
				msg = (String)context.getText(R.string.preJFmsg);
				break;
			default:
				msg = "";
			break;
			}
			final ProgressDialog dialog = ProgressDialog.show(
					v.getContext(),
					null,
					msg);

			switch (butID)
			{
			case R.id.ButtonNBH:
				tv = (TextView)findViewById(R.id.EditTextNBHUrl);
				final String NBH = String.valueOf(tv.getText());

				thread = new Thread(new Runnable() {
					public void run() {
						String localPath = download(NBH, "/sdcard/");
						if (NBH.endsWith(".zip"))
							localPath = unzipFile(localPath);
						if (!(localPath.equals("/sdcard/DREAIMG.nbh")))
							RenameFile(localPath,"/sdcard/DREAIMG.nbh");
						dialog.cancel();
						displayMsg((String)context.getText(R.string.postNBHmsg));
					}
				});
				thread.start();
				break;
			case R.id.ButtonIMGSPL:
				tv = (TextView)findViewById(R.id.EditTextIMGUrl);
				final String IMG = String.valueOf(tv.getText());
				tv = (TextView)findViewById(R.id.EditTextSPLUrl);
				final String SPL= String.valueOf(tv.getText());

				thread = new Thread(new Runnable() {
					public void run() {
						String localPath = download(IMG, "/sdcard/");
						if (IMG.endsWith(".zip"))
							localPath = unzipFile(localPath);
						if (!(localPath.equals("/sdcard/recovery.img")))
							RenameFile(localPath,"/sdcard/recovery.img");
						localPath = download(SPL, "/sdcard/");
						if (!(localPath.equals("/sdcard/update.zip")))
							RenameFile(localPath,"/sdcard/update.zip");
						dialog.cancel();
						displayMsg((String)context.getText(R.string.postIMGSPLmsg));
					}
				});
				thread.start();
				break;
			case R.id.ButtonROOT:
				//run script

				thread = new Thread(new Runnable() {
					public void run() {
						try {
							Thread.sleep(5000);
						} catch (InterruptedException e) {
							e.printStackTrace();
						}
						CheckDLFile("root.sh", true);
						try {
							Thread.sleep(5000);
						} catch (InterruptedException e) {
							e.printStackTrace();
						}
						/*
						File file = new File("/system/bin/su");
						String result = "";
						if (file.exists())
							result = "su " + exec("/system/bin/su", dataPath + "root.sh", null);
						else
							result = "sh " + exec("/system/bin/sh", dataPath + "root.sh", null);
						
						simulateKeystroke(KeyEvent.KEYCODE_ENTER);
						simulateKeystroke(KeyEvent.KEYCODE_R);
						simulateKeystroke(KeyEvent.KEYCODE_E);
						simulateKeystroke(KeyEvent.KEYCODE_B);
						simulateKeystroke(KeyEvent.KEYCODE_O);
						simulateKeystroke(KeyEvent.KEYCODE_O);
						simulateKeystroke(KeyEvent.KEYCODE_T);
						simulateKeystroke(KeyEvent.KEYCODE_ENTER);
						
						//  sh /data/data/root.root/root.sh
						simulateKeystroke(KeyEvent.KEYCODE_ENTER);
						simulateKeystroke(KeyEvent.KEYCODE_S);
						simulateKeystroke(KeyEvent.KEYCODE_H);
						simulateKeystroke(KeyEvent.KEYCODE_SPACE);
						simulateKeystroke(KeyEvent.KEYCODE_SLASH);
						simulateKeystroke(KeyEvent.KEYCODE_D);
						simulateKeystroke(KeyEvent.KEYCODE_A);
						simulateKeystroke(KeyEvent.KEYCODE_T);
						simulateKeystroke(KeyEvent.KEYCODE_A);
						simulateKeystroke(KeyEvent.KEYCODE_SLASH);
						simulateKeystroke(KeyEvent.KEYCODE_D);
						simulateKeystroke(KeyEvent.KEYCODE_A);
						simulateKeystroke(KeyEvent.KEYCODE_T);
						simulateKeystroke(KeyEvent.KEYCODE_A);
						simulateKeystroke(KeyEvent.KEYCODE_SLASH);
						simulateKeystroke(KeyEvent.KEYCODE_R);
						simulateKeystroke(KeyEvent.KEYCODE_O);
						simulateKeystroke(KeyEvent.KEYCODE_O);
						simulateKeystroke(KeyEvent.KEYCODE_T);
						simulateKeystroke(KeyEvent.KEYCODE_PERIOD);
						simulateKeystroke(KeyEvent.KEYCODE_R);
						simulateKeystroke(KeyEvent.KEYCODE_O);
						simulateKeystroke(KeyEvent.KEYCODE_O);
						simulateKeystroke(KeyEvent.KEYCODE_T);
						simulateKeystroke(KeyEvent.KEYCODE_SLASH);
						simulateKeystroke(KeyEvent.KEYCODE_R);
						simulateKeystroke(KeyEvent.KEYCODE_O);
						simulateKeystroke(KeyEvent.KEYCODE_O);
						simulateKeystroke(KeyEvent.KEYCODE_T);
						simulateKeystroke(KeyEvent.KEYCODE_PERIOD);
						simulateKeystroke(KeyEvent.KEYCODE_S);
						simulateKeystroke(KeyEvent.KEYCODE_H);
						simulateKeystroke(KeyEvent.KEYCODE_ENTER);
						*/
						
						try {
							if (isProcessRunning("telnetd"))
							{
							try {
								String result = doTelnetCmd();
								dialog.cancel();
								if (result.contains("Success"))
									displayMsg((String)context.getText(R.string.postROOTmsg));
								else
									displayMsg(result);
							} catch (Exception e) {
								Log.e("root",e.getMessage());
								e.printStackTrace();
								dialog.cancel();
								displayMsg(e.getMessage());
							}
							}
							else
							{
								dialog.cancel();
								displayMsg((String)context.getText(R.string.postROOTerrorMsg));
							}
						} catch (Exception e) {
							Log.e("root",e.getMessage());
							e.printStackTrace();
							dialog.cancel();
							displayMsg(e.getMessage());
						}
						

					}
				});
				thread.start();
				break;
			case R.id.ButtonJF:
				tv = (TextView)findViewById(R.id.EditTextJFURL);
				final String JF= String.valueOf(tv.getText());

				thread = new Thread(new Runnable() {
					public void run() {
						String localPath = download(JF, "/sdcard/");
						if (!(localPath.equals("/sdcard/update.zip")))
							RenameFile(localPath,"/sdcard/update.zip");
						dialog.cancel();
						displayMsg((String)context.getText(R.string.postJFmsg));
					}
				});
				thread.start();
				break;
			}

		}
	};

    public static boolean isProcessRunning(String processName) throws Exception {
        boolean running = false;
    	Process process = null;
		process = Runtime.getRuntime().exec("ps");
        BufferedReader in = new BufferedReader(new InputStreamReader(process.getInputStream()));
        String line = null;
        while ((line = in.readLine()) != null) {
            if (line.contains(processName)) {
            	running = true;
            	break;
            }
        }
        in.close();
        process.waitFor();
		return running;
    }
    
    /** Wrapper-function taking a KeyCode.
     * A complete KeyStroke is DOWN and UP Action on a key! */
    private void simulateKeystroke(final int KeyCode) {
    	Runnable proc = new Runnable() {
			public void run() {
		    	context.dispatchKeyEvent(new KeyEvent(KeyEvent.ACTION_DOWN, KeyCode));
		    	context.dispatchKeyEvent(new KeyEvent(KeyEvent.ACTION_UP, KeyCode));
			}
		};
		handler.post(proc);
    }
    
private static String doTelnetCmd() throws Exception
{
	String cmd = "sh /sdcard/root.sh\n";
    Socket sock = new Socket ("localhost", 23);
    BufferedWriter wr = new BufferedWriter(new OutputStreamWriter(sock.getOutputStream(), "UTF8"),4096);
    BufferedReader rd = new BufferedReader(new InputStreamReader(sock.getInputStream()));
  
    wr.write(cmd);
    wr.flush();

	String output = "";
	try {
		int a=rd.read();
		while (a != -1){
			output += (char) a;
			//Log.e("root", output);
			if((output.endsWith("Success"))||(output.endsWith("failed")))
				break;
			else
				a=rd.read();
		}
	} catch (IOException e) {
		// It seems IOException is thrown when it reaches EOF.
	}	

    wr.close();
    wr = null;
	rd.close();
	rd = null;
    sock.close();
    sock = null;

	return output;
	    
}


}